#include "Communication.h"

SOCKET m_socket;

bool socketConnect() {// Initialize Winsock.
    WSADATA wsaData;
    int iResult = WSAStartup(MAKEWORD(2,2), &wsaData);
    if (iResult != NO_ERROR)
		printf("Client: Error at WSAStartup().\n");
    else
        printf("Client: WSAStartup() is OK.\n");

	// Create a socket.
    m_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if (m_socket == INVALID_SOCKET) {
        printf("Client: socket() - Error at socket(): %ld\n", WSAGetLastError());
        WSACleanup();
        return false;
    }
	else
       printf("Client: socket() is OK.\n");

    // Connect to a server.
    sockaddr_in clientService;
    clientService.sin_family = AF_INET;
    // Just test using the localhost, you can try other IP address
    clientService.sin_addr.s_addr = inet_addr("127.0.0.1");
    clientService.sin_port = htons(60070);

    if (connect(m_socket, (SOCKADDR*)&clientService, sizeof(clientService)) == SOCKET_ERROR) {
        printf("Client: connect() - Failed to connect.\n");
        WSACleanup();
        return false;
    }
    else {
       printf("Client: connect() is OK.\n");
       printf("Client: Can start sending and receiving data...\n");
    }

    // Send and receive data.
	printf("Connected\n");
	return true;
}

void envia(const char *s, int len) {
	int bytesSent = send(m_socket, s, len, 0);
	if(bytesSent == SOCKET_ERROR)
		printf("Client: send() error %ld.\n", WSAGetLastError());
}

void recebe(char *ans) {
	int bytesRecv = SOCKET_ERROR;
	int pos = 0;
	while (true) {
		recv(m_socket, &ans[pos], 1, 0);
		if (ans[pos] == '\n')
			break;
		pos++;
	}
	ans[pos] = 0;
	cout << "prolog answered: " << ans << endl;
}

string recebe() {
	int bytesRecv = SOCKET_ERROR;
	char c = 0;
	string ans = "";
	while (true) {
		recv(m_socket, &c, 1, 0);
		if (c == '\n')
			break;
		ans += c;
	}
	return ans;
}

void quit() {
	cout << "Asking prolog to quit" << endl;
	char buff[] = "quit.\n";
	envia(buff, 6);
	char ans[128];
	recebe(ans);
}
/*
int main() {
	socketConnect();
	char *s = "comando(1, 2).\n";
	envia(s, strlen(s));
	char ans[128];
	recebe(ans);
	quit();
	getchar();
	return 0;
}*/

Move getCompMove(string board, PlayerType player){
	stringstream ss;
	ss << "get_player_move(" << (player == WHITE ? 'w' : 'b') <<',' << board <<").\n";
	envia(ss.str().c_str(),ss.str().size());
	string answer = recebe();
	int xi,yi,xf,yf,n_checkers;
	char move_type[10];
	sscanf(answer.c_str(),"[%d,%d,%d,%d,%d,%s",&xi,&yi,&xf,&yf,&n_checkers,&move_type);

	Move move;
	move.player = player;
	move.xi = xi;
	move.yi = yi;
	move.xf = xf;
	move.yf = yf;
	move.n_checkers = n_checkers;
	if(strcmp(move_type,"capture].")==0 )
		move.moveType = CAPTURE;
	else if(strcmp(move_type,"remove].")==0 )
		move.moveType = REMOVE;
	else if(strcmp(move_type,"merge].")==0 )
		move.moveType = MERGE;
	else if(strcmp(move_type,"move].")==0 )
		move.moveType = NORMAL;
	else{
		printf("move nao valido\n");
		getchar();
		exit(1);
	}

	return move;
}

vector<Move> getPlayerMoves(string board, PlayerType player, int x, int y){
	stringstream ss;
	ss << "getPlayerMoves(" << (player == WHITE ? 'w' : 'b') << ',' << x << '-' << y << ',' << board <<").\n";
	envia(ss.str().c_str(), ss.str().size());
	string answer = recebe();
	cout << answer << endl;

	vector<Move> moves;

	size_t move_begin = answer.find('[',1);
	size_t move_end;
	
	vector<Move> remove_moves;

	while(move_begin != std::string::npos){
		move_end = answer.find(']',move_begin);
		string move_string = answer.substr(move_begin + 1, move_end - move_begin -1);

		int xf,yf,n_checkers;
		char move_type[10];
		sscanf(move_string.c_str(),"%d,%d,%d,%s",&xf,&yf,&n_checkers,&move_type);
		Move move;
		move.player= player;
		move.xi = x;
		move.yi = y;
		move.xf = xf;
		move.yf = yf;
		move.n_checkers = n_checkers;
		if(strcmp(move_type,"capture")==0 )
			move.moveType = CAPTURE;
		else if(strcmp(move_type,"remove")==0 )
			move.moveType = REMOVE;
		else if(strcmp(move_type,"merge")==0 )
			move.moveType = MERGE;
		else if(strcmp(move_type,"move")==0 )
			move.moveType = NORMAL;
		else{
			printf("move nao valido\n");
			getchar();
			exit(1);
		}

		if(move.moveType == REMOVE){
			if(remove_moves.empty() || n_checkers == remove_moves[0].n_checkers)
				remove_moves.push_back(move);
			else if(n_checkers < remove_moves[0].n_checkers  ){
				remove_moves.clear();
				remove_moves.push_back(move);
			}
		}
		else
			moves.push_back(move);
		move_begin = answer.find('[',move_end);
	}
	moves.insert(moves.end(),remove_moves.begin(),remove_moves.end());
	return moves;
}

vector< pair<int,int> > getPlayerPositions(string board, PlayerType player){
	stringstream ss;
	ss << "get_all_pos_player(" << (player == WHITE ? 'w' : 'b') << ',' << board <<").\n";
	string request = ss.str();
	envia(request.c_str(), request.size());
	string answer = recebe();
	vector< pair<int,int> > positions;

	int i=1;
	char c;
	while(i<answer.size()){
		c = answer[i];
		if(c == ']')
			break;
		switch(c){
			case ',':
				++i;
				break;
			default:
				int x = atoi(&c);
				i += 2;
				c = answer[i];
				int y = atoi(&c);
				positions.push_back( pair<int,int>(x,y) );
				++i;
		}
	}
	return positions;
}